﻿using AutoMapper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Linq;
using System.Security.Cryptography;
using housingsafety.server.Caching.Core;
using housingsafety.server.Entities;
using housingsafety.server.Entities.DataModels;
using housingsafety.server.Helpers;
using housingsafety.server.Models;
using housingsafety.server.Repository;
using housingsafety.server.Repository.Extensions;
using housingsafety.server.Security;
using housingsafety.server.Snowflake;
using System.Collections.Generic;
using System.ComponentModel;
using Microsoft.EntityFrameworkCore;
using System.Transactions;

namespace housingsafety.server.Controllers
{
    /// <summary>
    /// 调查单位管理
    /// </summary>
    public class SurveyUnitController : BaseController<SurveyUnitController>
    {
        private readonly ICache _cache;
        private readonly IMapper _mapper;
        private readonly ZmDbContext _dbContext;
        private readonly IRepository<ZmUser> _userRepository;
        private readonly IRepository<ZmSurveyUnit> _surveyUnitRepository;

        public SurveyUnitController(IRepository<ZmUser> userRepository
            , IMapper mapper, ICacheProvider cacheProvider, ZmDbContext dbContext
            , ILogger<SurveyUnitController> logger
            , IRepository<ZmSystemLog> systemLogRepository
            , IRepository<ZmSurveyUnit> surveyUnitRepository) : base(logger, systemLogRepository)
        {
            _mapper = mapper;
            _dbContext = dbContext;
            _cache = cacheProvider.CreateCache();
            _userRepository = userRepository;
            _surveyUnitRepository = surveyUnitRepository;
        }

        /// <summary>
        /// 获取调查单位列表
        /// </summary>
        /// <param name="pageRequest">查询参数</param>
        /// <returns></returns>
        [HttpGet("survey-unit/list")]
        [Produces("application/json")]
        [ProducesResponseType(typeof(RespRet<Page<SurveyUnitDto>>), 200)]
        [ProducesResponseType(403)]
        public RespRet<Page<SurveyUnitDto>> List([FromQuery] SimplePageRequestInput pageRequest)
        {
            if (pageRequest.PageIndex < 0)
            {
                return new RespRet<Page<SurveyUnitDto>>(false, "PageIndex must >= 0");
            }

            var adminUserNumber = this.CurrentUser();
            if (string.IsNullOrEmpty(adminUserNumber))
            {
                return new RespRet<Page<SurveyUnitDto>>(false, "user not logined");
            }

            var curuser = _userRepository.FirstOrDefault(u => u.Number == adminUserNumber && u.IsDelete != 1);
            if (null == curuser)
            {
                return new RespRet<Page<SurveyUnitDto>>(false, "用户名不存在");
            }

            var curuserDto = _mapper.Map<UserDto>(curuser);

            // 获取相同行政区、角色、组的管理员
            var groupFld = "\"group\"";
            var sameDistrictUser = _dbContext.ZmUser.FromSqlRaw($@"SELECT * FROM zm_user 
WHERE district->>'RegionCode' = '{curuserDto.District.RegionCode}' 
and role_type = {curuser.RoleType} and  {groupFld} = {curuser.Group}")?.Select(_ => _.Number)?.ToList();
            if (null == sameDistrictUser || sameDistrictUser.Count < 1)
            {
                return new RespRet<Page<SurveyUnitDto>>(false, "没有管理员");
            }

            Page<SurveyUnitDto> datas = null;
            if (curuserDto.Role == PermissionRoleType.Area)
            {
                datas = (from unit in _dbContext.ZmSurveyUnit
                         join user in _dbContext.ZmUser on unit.Id equals user.SurveyUnitId into joinA
                         from b in joinA
                         where unit.IsDelete != 1
                         where b.RoleType == 7
                         where string.IsNullOrWhiteSpace(pageRequest.unitname) ? 1==1 : unit.Name.Contains( pageRequest.unitname)
                         where string.IsNullOrWhiteSpace(pageRequest.principalsName) ? 1 == 1 : b.Nickname.Contains( pageRequest.principalsName)
                         where sameDistrictUser.Contains(unit.CreateBy)
                         select new SurveyUnitDto
                         {
                             Id = unit.Id,
                             Principals = b.Number,
                             Name = unit.Name,
                             PrincipalsName = b.Uname + "(" + b.Nickname + ")",
                             ModifiedOn = unit.ModifiedOn
                         })
                         .ToPagedList(pageRequest.PageIndex + 1, pageRequest.Limit);
                return new RespRet<Page<SurveyUnitDto>>(true, "Ok", datas);
            }
            else if (curuserDto.Role == PermissionRoleType.City)
            {
                datas = (from unit in _dbContext.ZmSurveyUnit
                         join user in _dbContext.ZmUser on unit.Id equals user.SurveyUnitId into joinA
                         from b in joinA
                         where unit.IsDelete != 1
                         where b.RoleType == 9
                         where string.IsNullOrWhiteSpace(pageRequest.unitname) ? 1 == 1 : unit.Name.Contains(pageRequest.unitname)
                         where string.IsNullOrWhiteSpace(pageRequest.principalsName) ? 1 == 1 : b.Nickname.Contains(pageRequest.principalsName)

                         where sameDistrictUser.Contains(unit.CreateBy)
                         select new SurveyUnitDto
                         {
                             Id = unit.Id,
                             Principals = b.Number,
                             Name = unit.Name,
                             PrincipalsName = b.Uname+"("+b.Nickname+")",
                             ModifiedOn = unit.ModifiedOn
                         })
                         .ToPagedList(pageRequest.PageIndex + 1, pageRequest.Limit);
                return new RespRet<Page<SurveyUnitDto>>(true, "Ok", datas);
            }

            return new RespRet<Page<SurveyUnitDto>>(true, "Ok", datas);
        }

        /// <summary>
        /// 获取单位信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("survey-unit/{id}/info")]
        [Produces("application/json")]
        [ProducesResponseType(typeof(RespRet<SurveyUnitDto>), 200)]
        [ProducesResponseType(403)]
        public RespRet<SurveyUnitDto> GetInfo([FromRoute] string id)
        {
            if (!ModelState.IsValid)
            {
                return new RespRet<SurveyUnitDto>(false, "Invalid Request");
            }

            if (string.IsNullOrEmpty(id))
            {
                return new RespRet<SurveyUnitDto>(false, "id必须输入");
            }

            var adminUserNumber = this.CurrentUser();
            if (string.IsNullOrEmpty(adminUserNumber))
            {
                return new RespRet<SurveyUnitDto>(false, "user not logined");
            }

            var data = _surveyUnitRepository.FirstOrDefault(u => u.Id == id && u.IsDelete != 1);
            if (null == data)
            {
                return new RespRet<SurveyUnitDto>(false, "不存在");
            }

            return new RespRet<SurveyUnitDto>(true, "Ok", _mapper.Map<SurveyUnitDto>(data));
        }

        /// <summary>
        /// 判断名称是否已存在
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        [HttpGet("survey-unit/exists")]
        [Produces("application/json")]
        [ProducesResponseType(typeof(RespRet<bool>), 200)]
        public RespRet Exists([FromQuery] string name,[FromQuery] string id)
        {
            if (string.IsNullOrEmpty(name))
            {
                return new RespRet<bool>(false, "Invalid param");
            }

            var userNumber = this.CurrentUser();
            if (string.IsNullOrEmpty(userNumber))
            {
                return new RespRet<bool>(false, "user not logined");
            }

            var curuser = _userRepository.FirstOrDefault(u => u.Number == userNumber && u.IsDelete != 1);
            if (null == curuser)
            {
                return new RespRet<Page<SurveyUnitDto>>(false, "用户名不存在");
            }

            var curuserDto = _mapper.Map<UserDto>(curuser);

            // 获取相同行政区、角色、组的管理员
            var groupFld = "\"group\"";
            var sameDistrictUser = _dbContext.ZmUser.FromSqlRaw($@"SELECT * FROM zm_user 
WHERE district->>'RegionCode' = '{curuserDto.District.RegionCode}' 
and role_type = {curuser.RoleType} and  {groupFld} = {curuser.Group}")?.Select(_ => _.Number)?.ToList();
            if (null == sameDistrictUser || sameDistrictUser.Count < 1)
            {
                return new RespRet<bool>(false, "没有管理员");
            }

            var count = _surveyUnitRepository.Count(u => string.Equals(u.Name, name)
            && u.IsDelete != 1 && sameDistrictUser.Contains(u.CreateBy));
            if (!string.IsNullOrWhiteSpace(id))
            {
                count= _surveyUnitRepository.Count(u => string.Equals(u.Name, name)
             && u.IsDelete != 1&&u.Id!=id && sameDistrictUser.Contains(u.CreateBy));
            }

            if (count > 0)
            {
                return new RespRet<bool>(true, "Ok", true);
            }

            return new RespRet<bool>(true, "Ok", false);
        }

        /// <summary>
        /// 创建调查单位
        /// </summary>
        /// <param name="request">请求参数</param>
        /// <returns>创建用户是否成功，并返回唯一编号</returns>
        [HttpPost("survey-unit/create")]
        [Produces("application/json")]
        [ProducesResponseType(typeof(RespRet<string>), 200)]
        [ProducesResponseType(403)]
        public RespRet Create([FromBody] CreateSurveyUnitInput request)
        {
            if (!ModelState.IsValid)
            {
                return new RespRet<string>(false, "Invalid Request");
            }

            var userNumber = this.CurrentUser();
            if (string.IsNullOrEmpty(userNumber))
            {
                return new RespRet<string>(false, "user not logined");
            }

            var curuser = _userRepository.FirstOrDefault(u => u.Number == userNumber && u.IsDelete != 1);
            if (null == curuser)
            {
                return new RespRet<Page<SurveyUnitDto>>(false, "用户名不存在");
            }

            var curuserDto = _mapper.Map<UserDto>(curuser);

            if (curuserDto.Role != PermissionRoleType.City && curuserDto.Role != PermissionRoleType.Area)
            {
                return new RespRet<Page<SurveyUnitDto>>(false, "非市级管理员或者区县管理员，不允许创建单位");
            }

            // 获取相同行政区、角色、组的管理员
            var groupFld = "\"group\"";
            var sameDistrictUser = _dbContext.ZmUser.FromSqlRaw($@"SELECT * FROM zm_user 
WHERE district->>'RegionCode' = '{curuserDto.District.RegionCode}' 
and role_type = {curuser.RoleType} and  {groupFld} = {curuser.Group}")?.Select(_ => _.Number)?.ToList();
            if (null == sameDistrictUser || sameDistrictUser.Count < 1)
            {
                return new RespRet<string>(false, "没有管理员");
            }

            var count = _surveyUnitRepository.Count(u => string.Equals(u.Name, request.Name)
            && u.IsDelete != 1 && sameDistrictUser.Contains(u.CreateBy));
            if (count > 0)
            {
                return new RespRet<string>(false, "名称重复");
            }

            var principalsUser = _userRepository.FirstOrDefault(u => u.Number == request.Principals
            && u.IsDelete != 1);
            if (null == principalsUser)
            {
                return new RespRet<Page<SurveyUnitDto>>(false, "单位负责人不存在");
            }

            if (!string.IsNullOrEmpty(principalsUser.SurveyUnitId))
            {
                return new RespRet<Page<SurveyUnitDto>>(false, "单位负责人已经绑定别的单位了，不允许再次绑定");
            }

            var ipAddress = this.IpAddress();
            var id = SequentialGuid.SequentialGuidGenerator.Instance.NewGuid().ToString("N");

            using (TransactionScope trans = new TransactionScope())
            {
                try
                {
                    var data = new ZmSurveyUnit
                    {
                        Id = id,
                        Name = request.Name,
                        CreateBy = userNumber,
                        CreateOn = DateTime.Now,
                        CreateIp = ipAddress,
                        ModifiedBy = userNumber,
                        ModifiedOn = DateTime.Now,
                        ModifiedIp = ipAddress
                    };

                    _surveyUnitRepository.Insert(data);
                    _surveyUnitRepository.SaveChanges();

                    principalsUser.SurveyUnitId = id;
                    _userRepository.Update(principalsUser);
                    _userRepository.SaveChanges();

                    _dbContext.Database.ExecuteSqlInterpolated($@"update zm_user set survey_unit_id = {id} 
where create_by = {principalsUser.Number}");

                    trans.Complete();
                }
                catch (Exception e)
                {
                    try
                    {
                        Transaction.Current.Rollback();
                    }
                    catch (Exception exception)
                    {
                        Console.WriteLine(exception);
                    }
                    return new RespRet<string>(false, "失败");
                }
            }
            return new RespRet<string>(true, "Ok", id);
        }

        /// <summary>
        /// 编辑调查单位
        /// </summary>
        /// <param name="id"></param>
        /// <param name="request">请求参数</param>
        /// <returns></returns>
        [HttpPost("survey-unit/{id}/edit")]
        [Produces("application/json")]
        [ProducesResponseType(typeof(RespRet), 200)]
        [ProducesResponseType(403)]
        public RespRet Edit([FromRoute] string id, [FromBody] EditSurveyUnitInput request)
        {
            var userNumber = this.CurrentUser();
            if (string.IsNullOrEmpty(userNumber))
            {
                return new RespRet<string>(false, "user not logined");
            }

            var data = _surveyUnitRepository.FirstOrDefault(u => u.Id == id && u.IsDelete != 1);
            if (null == data)
            {
                return new RespRet(false, "不存在");
            }

            if (!string.Equals(data.Name, request.Name))
            {
                var curuser = _userRepository.FirstOrDefault(u => u.Number == userNumber && u.IsDelete != 1);
                if (null == curuser)
                {
                    return new RespRet<Page<SurveyUnitDto>>(false, "用户名不存在");
                }

                var curuserDto = _mapper.Map<UserDto>(curuser);

                // 获取相同行政区、角色、组的管理员
                var groupFld = "\"group\"";
                var sameDistrictUser = _dbContext.ZmUser.FromSqlRaw($@"SELECT * FROM zm_user 
WHERE district->>'RegionCode' = '{curuserDto.District.RegionCode}' 
and role_type = {curuser.RoleType} and  {groupFld} = {curuser.Group}")?.Select(_ => _.Number)?.ToList();
                if (null == sameDistrictUser || sameDistrictUser.Count < 1)
                {
                    return new RespRet<string>(false, "没有管理员");
                }

                var count = _surveyUnitRepository.Count(u => string.Equals(u.Name, request.Name)
                && u.IsDelete != 1 && sameDistrictUser.Contains(u.CreateBy)&&u.Id!=id);
                if (count > 0)
                {
                    return new RespRet<string>(false, "名称重复");
                }
            }

            using (TransactionScope trans = new TransactionScope())
            {
                try
                {

                    if (!string.IsNullOrEmpty(request.Principals))
                    {
                        var oldPrincipalsUser = _userRepository.FirstOrDefault(u => u.SurveyUnitId == data.Id
                        && u.IsDelete != 1);
                        if (null != oldPrincipalsUser && oldPrincipalsUser.Number != request.Principals)
                        {
                            var principalsUser = _userRepository
                                .FirstOrDefault(u => u.Number == request.Principals
                            && u.IsDelete != 1);
                            if (null == principalsUser)
                            {
                                return new RespRet<Page<SurveyUnitDto>>(false, "单位负责人不存在");
                            }

                            principalsUser.SurveyUnitId = data.Id;
                            _userRepository.Update(principalsUser);
                            _userRepository.SaveChanges();

                            oldPrincipalsUser.SurveyUnitId = null;
                            _userRepository.Update(oldPrincipalsUser);
                            _userRepository.SaveChanges();

                            _dbContext.Database.ExecuteSqlInterpolated($@"update zm_user set survey_unit_id = {id} 
where create_by = {principalsUser.Number}");
                        }
                    }

                    data.Name = request.Name;
                    data.ModifiedBy = userNumber;
                    data.ModifiedOn = DateTime.Now;
                    data.ModifiedIp = this.IpAddress();

                    _surveyUnitRepository.Update(data);
                    _surveyUnitRepository.SaveChanges();

                    trans.Complete();
                }
                catch (Exception e)
                {
                    try
                    {
                        Transaction.Current.Rollback();
                    }
                    catch (Exception exception)
                    {
                        Console.WriteLine(exception);
                    }
                    return new RespRet<string>(false, "失败");
                }
            }

            return new RespRet<string>(true, "Ok", id);
        }

        /// <summary>
        /// 删除调查单位
        /// </summary>
        /// <param name="id">唯一编号</param>
        /// <returns></returns>
        [HttpPost("survey-unit/{id}/delete")]
        [Produces("application/json")]
        [ProducesResponseType(typeof(RespRet), 200)]
        [ProducesResponseType(403)]
        public RespRet Delete([FromRoute] string id)
        {
            if (string.IsNullOrEmpty(id))
            {
                return new RespRet(false, "userNumber not allow empty");
            }

            var adminUserNumber = this.CurrentUser();
            if (string.IsNullOrEmpty(adminUserNumber))
            {
                return new RespRet(false, "user not logined");
            }

            var data = _surveyUnitRepository.FirstOrDefault(u => u.Id == id && u.IsDelete != 1);
            if (null == data)
            {
                return new RespRet(false, "不存在");
            }

            using (TransactionScope trans = new TransactionScope())
            {
                try
                {
                    data.DeleteBy = adminUserNumber;
                    _surveyUnitRepository.Delete(data);
                    _surveyUnitRepository.SaveChanges();

                    _dbContext.Database.ExecuteSqlInterpolated($@"update zm_user set survey_unit_id = null 
where survey_unit_id = { data.Id}");

                    trans.Complete();
                }
                catch (Exception e)
                {
                    try
                    {
                        Transaction.Current.Rollback();
                    }
                    catch (Exception exception)
                    {
                        Console.WriteLine(exception);
                    }
                    return new RespRet<string>(false, "失败");
                }
            }

            return new RespRet(true, "Ok");
        }
    }
}
